package com.woniuxy.lab.woniu_lab.util;

import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.api.command.CreateContainerCmd;
import com.github.dockerjava.api.command.CreateContainerResponse;
import com.github.dockerjava.api.command.CreateNetworkResponse;
import com.github.dockerjava.api.command.InspectContainerResponse;
import com.github.dockerjava.api.exception.NotFoundException;
import com.github.dockerjava.api.model.*;
import com.github.dockerjava.core.DefaultDockerClientConfig;
import com.github.dockerjava.core.DockerClientBuilder;
import com.github.dockerjava.core.DockerClientConfig;
import com.github.dockerjava.netty.NettyDockerCmdExecFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.util.List;
import java.util.Objects;

@Slf4j
public class DockerUtil {

    private static DockerUtil instance = null;



    private static final String DOCKER_API_VERSION = "1.38";

    private static DockerClient client;

    private DockerUtil(String dockerHost,String dockerPort) {
        DockerClientConfig customConfig = DefaultDockerClientConfig.createDefaultConfigBuilder()
                .withDockerHost("tcp://" + dockerHost + ":"+dockerPort)
                .withDockerTlsVerify(false)
                .build();
        client = DockerClientBuilder.getInstance(customConfig)
                .withDockerCmdExecFactory(new NettyDockerCmdExecFactory())
                .build();
        log.info("创建client");
    }

    public static DockerUtil getInstance(String dockerHost,String dockerPort) {
        if (instance == null) {
            instance = new DockerUtil(dockerHost,dockerPort);
        }
        return instance;
    }

    /**
     *  通过容器名返回容器对象
     * @param name 容器名
     * @return 容器对象
     */
    public Container getContainerByName(String name){
        Container container = null;
        List<Container> containerList = client.listContainersCmd().withShowAll(true).exec();
        for (Container c : containerList) {
            System.out.println(c.getNames()[0]);
            if (c.getNames()[0].equals("/"+name)){
                container=c;
                break;
            }
        }
        return container;
    }

    /**
     * 启动暂停中的容器
     * @param id dockerId
     */
    public void startContainerById(String id){
        client.startContainerCmd(id).exec();
    }

    /**
     * 删除容器
     * @param id 容器id
     * @return 成功状态
     */
    private Boolean rmContainerById(String id){
        try {
            client.removeContainerCmd(id).exec();
        } catch (NotFoundException e) {
            return false;
        }
        return true;
    }

    /**
     * 构建镜像
     * @param imageName 镜像
     * @param imageTag 镜像的版本
     * @param path dockerFile路径
     * @return 镜像id
     */
//    public static String buildImage(DockerClient client,String imageName,String imageTag,String path) throws FileNotFoundException {
//
//        ImmutableSet<String> tag = ImmutableSet.of(imageName + ":" + imageTag);
//        FileInputStream fileInputStream = new FileInputStream(path);
//        System.out.println(fileInputStream);
//        String imageId = client.buildImageCmd(fileInputStream)
//                .withTags(tag)
//
//                .awaitImageId();
//        closeDocker(client);
//        return imageId;
//    }


    /**
     *  创建容器 不是run是create
     * @param image 镜像名称+版本 redis:latest
     * @param CPort docker端口 -p
     * @param LPort 映射的linux端口 -p
     * @param name --name 名称
     * @param env 环境变量 -e
     * @param networkName 网络名 -h
     * @param LPath 服务路径
     * @param CPath 容器路径
     * @return 创建的容器对象
     */
    public CreateContainerResponse createContainer(String image,String CPort,String LPort,String name,
                                                   String env, String networkName,String LPath,String CPath) {
        HostConfig hostConfig = new HostConfig().
                withPortBindings(PortBinding.parse(""+LPort+":"+CPort))
                .withMemory(256 * 1024 * 1024L).withCpuCount(256L).withAutoRemove(true);
//        .
        if (CPath!=null && LPath!=null){
            hostConfig.withBinds(new Bind(LPath,new Volume(CPath)));
        }
        CreateContainerCmd containerCmd = client.createContainerCmd(image).withName(name)
                .withHostConfig(hostConfig);

        if (env!=null){
            containerCmd.withEnv(env);
        }
        if (networkName!=null){
            containerCmd.withHostName(networkName);
        }
        //创建
        CreateContainerResponse response = containerCmd.exec();
        System.out.println(response.getId());

        return response;
    }

    /**
     * 停止容器
     * @param containerId 容器id
     */
    public void stopContainer(String containerId) {
        client.stopContainerCmd(containerId).exec();
    }
    /**
     * 删除容器
     * @param containerId 容器id
     */
    public void rmContainer(String containerId){
        client.removeContainerCmd(containerId).exec();
    }

    /**
     * repository 镜像名称:tag名称
     **/
    public void pullImage(String repository)  {
        client.pullImageCmd(repository);
    }

    /**
     * 判断镜像是否存在
     * @param imageName 判断容器是否存在
     * @return 布尔
     */
    public boolean existContainer(String imageName){
        boolean existFlag = false;
        List<Image> images = client.listImagesCmd().withImageNameFilter("busybox").exec();

        if (images.isEmpty()) existFlag = true;
        return existFlag;
    }

    /**
     * 判断容器是否启动
     * @param containerId 容器id
     * @return 启动成功true
     */
    public boolean getContainerState(String containerId){
        boolean startState = true;
        InspectContainerResponse inspectContainerResponse = client.inspectContainerCmd(containerId).exec();
        String status = inspectContainerResponse.getState().getStatus();
        if (!Objects.equals(status, "running")){
            startState=false;
            log.info("容器启动失败,当前容器状态{}",status);
        }
        return startState;
    }

    /**
     * 创建网络
     * @param networkName 网络名
     * @return 网络id
     */
    public String createNetwork(String networkName){
        CreateNetworkResponse networkResponse = client.createNetworkCmd().withName(networkName).exec();
        return networkResponse.getId();
    }
    /**
     * 创建网络
     * @param networkId 网络id
     */
    public void rmNetwork(String networkId){
        client.removeContainerCmd(networkId).exec();
    }

    public Boolean assertImageExist(String imagesName){
        boolean b = true;
        List<Image> exec = client.listImagesCmd().withImageNameFilter(imagesName).exec();
        if (exec.size()==0){
            b=false;
        }
        return b;
    }

}
